package com.google.code.p.odbcconnectionchecker;

import java.awt.EventQueue;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.TrayIcon;
import java.awt.TrayIcon.MessageType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;

import com.google.code.p.odbcconnectionchecker.UI.ConnectionStatusWindow;
import com.google.code.p.odbcconnectionchecker.UI.ConnectionWindow;
import com.google.code.p.odbcconnectionchecker.db.ConnectionStatus;

/*
 * Each connection is represented by a menu. 
 * Each menu has several menu items: 
 * 	- Add Action (more actions allowed)
 *  - Show Full Status 
 */

public class ConnectionMenu extends Menu implements Serializable {
	
	private static final long serialVersionUID = 4L;
	
	private String connectionName;
	private long refreshTimeSec;	
	private ConnectionCheckerMenuItemJdbc jdbcSetting;
	 
	//Log of connection statuses
	private ArrayList<ConnectionStatus> connectionStatus = new ArrayList<ConnectionStatus>();
	
	private static ConnectionCheckerPopupMenu popupMenu;
		
	/**
	 * Create a connection menu adding the default menu items
	 */
	public ConnectionMenu(){ 
		
		this.add(getCheckConnectionMenuItem());
		this.add(getLastStatusMenuItem());
		this.add(getShowHistoricalStatusesMenuItem());
		
		this.addSeparator();
		
		this.add(getModifyConnectionMenuItem());
		this.add(getDeleteConnectionMenuItem());
		
		jdbcSetting.setMyCm(this);
	}
	
/*	public void checkConnection () { 
		EventQueue.invokeLater(jdbcSetting);	
	}*/
	
	private MenuItem getLastStatusMenuItem() { 
		MenuItem mi = new MenuItem("Show Last Status");
		mi.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {	
				ConnectionCheckerTrayIcon.displayMessage(getConnectionName(), getLastStatusMessage(), TrayIcon.MessageType.INFO);
			}
		});
		return mi;
	}
	
	private String getLastStatusMessage() {
		String msg = "Status Not Available";
		if (!connectionStatus.isEmpty()) { 
			ConnectionStatus last_cs = connectionStatus.get(connectionStatus.size()-1);
			msg = last_cs.getConnectionActive()?"Active":("Inactive:" + last_cs.getErrorMessage());
			msg+= " - Checked performed @: " + last_cs.getConnectionTimestamp();
		}
		return msg;
	}
	
	/*
	 * Show the list of statuses so far collected
	 */
	private MenuItem getShowHistoricalStatusesMenuItem() {
		MenuItem mi = new MenuItem("Show Status History");
		mi.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				String data[][] = new String[connectionStatus.size()][3];
				String header[] = {"Timestamp","Status","Error"};
				int i = 0;
				for (ConnectionStatus cs : connectionStatus) {
					data[i][0] = cs.getConnectionTimestamp();
					data[i][1] = cs.getConnectionActive()?"active":"inactive";
					data[i][2] = cs.getErrorMessage();
					i++;
				}
				new ConnectionStatusWindow(header, data);
			} 	
		}
		);
		return mi;
	}
	
	/*
	 * Returns a Menu Item used for starting the checking of the connection status
	 */
	private MenuItem getCheckConnectionMenuItem() { 
		MenuItem mi = new MenuItem("Check Connection Status");
		mi.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				jdbcSetting.checkConnection();
			} 
		});
		return mi;		
	}
	
	public void addNewConnectionStatus (ConnectionStatus cs) { 
		connectionStatus.add(cs);
		newStatusUpdateMessage();
		newStatusUpdateLabel();
	}
	
	private void newStatusUpdateMessage() {

		if (connectionStatus.size()<=0) { 
			return;
		}
		
		ConnectionStatus curr_status = connectionStatus.get(connectionStatus.size()-1);
		
		String caption = this.getConnectionName();
		String message = curr_status.getErrorMessage();
		
		MessageType messageType;
		if (curr_status.getConnectionActive())
			messageType = TrayIcon.MessageType.INFO;
		else 
			messageType = TrayIcon.MessageType.ERROR;
		
		if (connectionStatus.size()>1) { 
			ConnectionStatus old_status;
			old_status = connectionStatus.get(connectionStatus.size()-2);
			if (curr_status.getConnectionActive() != old_status.getConnectionActive()) {
				ConnectionCheckerTrayIcon.displayMessage(caption, message, messageType);
			}
		} else { 
			ConnectionCheckerTrayIcon.displayMessage(caption, message, messageType);
		}
	}
	
	private void newStatusUpdateLabel () {
		if (connectionStatus.size()<= 0)  
			return;
		ConnectionStatus curr_status = connectionStatus.get(connectionStatus.size()-1);
		this.setLabel(getConnectionName() + (curr_status.getConnectionActive() ? ": Active" : ": Inactive"));		
	}

	/*
	 * Returns a Menu Item used for deleting the connection from the popup menu
	 */
	private MenuItem getDeleteConnectionMenuItem() { 
		MenuItem mi = new MenuItem("Delete");
		mi.addActionListener(new ActionListener () {
				@Override
				public void actionPerformed(ActionEvent e) {
					jdbcSetting.stopChecking();
					popupMenu.deleteConnection(ConnectionMenu.this);
				}
			}
		);
		return mi;
	}

	/*
	 * Returns a menu item for starting the modification of the connection parameters
	 */
	private MenuItem getModifyConnectionMenuItem() { 
		MenuItem mi = new MenuItem("Modify");
		mi.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						try {
							ConnectionWindow cw;
							cw = new ConnectionWindow();
							cw.existingConnection(ConnectionMenu.this);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				});	
			} 
		});
		return mi;
	}

	public void forceCheckConnection() {
		jdbcSetting.checkConnection();
	}
	
	public void setJdbcSettings(
			String connectionDriver, String connectionURL, 
			String username, String password, String driverURL) { 
		jdbcSetting = new ConnectionCheckerMenuItemJdbc();
		jdbcSetting.setConnectionDriver(connectionDriver);
		jdbcSetting.setConnectionURL(connectionURL);
		jdbcSetting.setUsername(username);
		jdbcSetting.setPassword(password);
		jdbcSetting.setDriverURL(driverURL);
	}
	
	/*
	 * Getters and Setters
	 */
	
	/**
	 * Gets the name of the connection
	 * @return A String
	 */
	public String getConnectionName() {
		return connectionName;
	}

	/**
	 * Sets the name of the connection
	 * @param connectionName
	 */
	public void setConnectionName(String connectionName) {
		this.connectionName = connectionName;
		this.setLabel(connectionName);
	}
	
	public static ConnectionCheckerPopupMenu getPopupMenu() {
		return popupMenu;
	}

	public static void setPopupMenu(ConnectionCheckerPopupMenu popupMenu) {
		ConnectionMenu.popupMenu = popupMenu;
	}

	public long getRefreshTimeSec() {
		return refreshTimeSec;
	}

	public void setRefreshTimeSec(long refreshTimeSec) {
		this.refreshTimeSec = refreshTimeSec;
	}

	public ConnectionCheckerMenuItemJdbc getJdbcSetting() {
		return jdbcSetting;
	}

	public void setJdbcSetting(ConnectionCheckerMenuItemJdbc jdbc_settings) {
		this.jdbcSetting = jdbc_settings;
	}
	
}
